home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Development
/
General
/
CW TCL port package
/
Template Munger
/
Source
/
MungeFiles.c
< prev
next >
Wrap
Text File
|
1994-05-30
|
11KB
|
429 lines
/*
* munge.c
*/
#include <string.h>
extern int * sprintf( char *, const char *, ... ) ;
unsigned char * C2P ( char* ) ;
extern void Idle ( void ) ;
extern short vRefNum ;
void MungeFile ( short vRef , long parID , unsigned char * fn, Boolean isTemplateDefn ) ;
void MungeFolder ( long parID ) ;
extern void Message ( unsigned char * ) ;
Boolean OpenOutfile();
void CloseOutfile();
void OutJunkChar(char theChar);
Boolean OutToken(char* theToken);
void OutNewLine();
void EndTemplateDeclaration();
void StartTemplateDefn();
void EndTemplateDefn();
CInfoPBRec rec ;
short err ;
Str63 name ;
Str255 str ;
Str63 outFileName; // name of template macro file name (typically ___.tm.h)
Str63 defnFileName; // name of template definition file name (typically ___.tem)
/* 0 == whitespace
1 == line feed chars
2 == digit
3 == colon
4 == letter
5 == bracket {
6 == bracket }
7 == angle bracket <
8 == angle bracket >
9 == start of comment
10 == left paren (, used to identify constructors
*/
char ch_type [ ] = {
/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F */
/* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
/* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 2 */ 0, 0, 0, 9, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 9,
/* 3 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 0, 7, 0, 8, 0,
/* 4 */ 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
/* 5 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 4,
/* 6 */ 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
/* 7 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 0, 6, 0, 0,
/* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* A */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* B */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* C */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* D */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* E */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
} ;
static void
CopyP ( unsigned char * from , unsigned char * to ) {
BlockMove ( from , to , 1 + * from ) ;
}
static void
ConcP ( unsigned char * to , unsigned char * tail ) {
short len = * tail ;
if ( len + * to > 255 ) {
len = 255 - * to ;
}
BlockMove ( tail + 1 , to + * to + 1 , len ) ;
* to += len ;
}
unsigned char *
C2P ( char * c ) {
int len = strlen ( c ) ;
if ( len ) {
BlockMove ( c , c + 1 , len ) ;
}
* c = len ;
return ( unsigned char * ) c ;
}
void
ErrMsg ( unsigned char * why , unsigned char * file , short code ) {
Str15 nn ;
long tick ;
static long lastBeep = 0 ;
NumToString ( code , nn ) ;
CopyP ( "\p ERROR " , str ) ;
ConcP ( str , why ) ;
ConcP ( str , "\p " ) ;
ConcP ( str , nn ) ;
ConcP ( str , "\p\r" ) ;
Message ( str ) ;
tick = TickCount ( ) + 5 ;
if ( lastBeep < tick - 600 ) { /* Only beep every 10 seconds if lots of errors */
SysBeep ( 20 ) ;
lastBeep = tick ;
}
}
static long
token ( Handle text , long pos , long end , char * tok , long * before, Boolean inTemplateDef ) {
char type ;
while ( pos < end ) {
while ( ! ch_type [ ( * text ) [ pos ] ] && pos < end ) { // Skip junk
if (inTemplateDef)
OutJunkChar((*text) [pos]); // pass junk chars to template file
pos ++ ;
}
* before = pos ;
* tok = ( * text ) [ pos ] ; // First token char
pos ++ ;
type = ch_type [ * tok ] ;
tok ++ ;
if (type == 9) { // •• ES: comment parsing
if (((*text)[pos] == '/') || ((*text)[pos] == '*')) {
*(tok++) = (*text)[pos++];
*tok = 0;
return pos;
}
}
if ( type == 1 ) { // line break
* tok = 0 ;
return pos ;
}
while ( pos < end ) {
char xTyp = ch_type [ ( * text ) [ pos ] ] ;
if ( ( xTyp != type ) &&
! ( type == 4 && xTyp == 2 ) ) { // Identifier number
* tok = 0 ;
return pos ;
}
* ( tok ++ ) = ( * text ) [ pos ++ ] ;
if (type == 9) { // comment: restrict to 2 characters
break;
}
}
}
* tok = 0 ;
return end ;
}
static int
Replace ( Handle text , long pos , long len , char * with ) {
Munger ( text , pos , NULL , len , with , strlen ( with ) ) ;
return strlen ( with ) - len ;
}
/* This function contains the total text of a TEXT file. */
/* The contents of the handle will be re-written to disk when done if true returned. */
/* Call Idle ( ) now and then for lengthy tasks */
// ES modified to look for template definitions
// uses routines in MakeTemplate.c to write macro files
// DOES NOT change source code
static void
MungeHandle ( Handle text , short vRef , long parID, Boolean isTemplateDefn ) {
long end = GetHandleSize ( text ) ;
long pos = 0 ;
char tok [ 256 ] ;
char other [ 256 ] ;
long before = 0 ;
long level = 0 ;
long oldPos ;
long oldBefore ;
int line = 1 ;
Boolean chng = 0 ;
Boolean tempFileReady = 0; // true if template file has been specified
Boolean inTemplateDef = 0; // flag if macro template file open
Boolean inLineComment = 0; // true if // encountered
Boolean inCComment = 0; // true if /* encountered */
if (isTemplateDefn)
StartTemplateDefn();
tok [ 0 ] = 0 ;
while ( pos < end ) {
oldPos = pos ;
oldBefore = before ;
tok [ 0 ] = 0 ;
if (inCComment) { // •• ES: special handling for /* */ type comments
while (pos < end) {
char tChar = (*text) [pos++];
if (tChar == 0x0D) { // new line?
inLineComment = 0;
line ++ ;
if (!(line % 10))
Idle();
} else if (tChar == '*') { // done yet?
if ((pos < end) && ((*text) [pos] == '/')) {
inCComment = 0;
pos++;
break;
}
}
}
continue;
}
pos = token ( text , pos , end , tok , & before, inTemplateDef || isTemplateDefn) ;
if ( ! tok [ 0 ] ) {
break ;
}
if ( ch_type [ tok [ 0 ] ] == 1 ) {
inLineComment = 0;
if (inTemplateDef || isTemplateDefn)
OutNewLine();
line ++ ;
if ( ! ( line % 10 ) ) {
Idle ( ) ;
}
continue; // no reason to continue parsing
}
if (inLineComment) {
if (!strcmp(tok, "__TEMPLATE__")) { // •• ES: look for template hints
if (inTemplateDef) {
sprintf(other, "\r• Error Line %d: nested template declarations ", line );
Message(C2P(other));
} else {
char* p;
while ((pos < end) && ((*text) [pos] == ' '))
pos++; // skip spaces
p = (char*) outFileName; // collect output file name
while ((pos < end) && ((*text) [pos] != ' ') && ((*text) [pos] != 0x0D))
*p++ = ((*text) [pos++]);
*p = 0;
while ((pos < end) && ((*text) [pos] == ' '))
pos++; // skip spaces
p = (char*) defnFileName; // collect definition file name
while ((pos < end) && ((*text) [pos] != ' ') && ((*text) [pos] != 0x0D))
*p++ = ((*text) [pos++]);
*p = 0;
C2P((char*) outFileName);
C2P((char*) defnFileName);
tempFileReady = true;
}
}
continue; // ignore all other syntax (it's a comment, after all!)
}
if (ch_type[tok[0]] == 9) { // •• ES: parse for comments
if (tok[0] == '/') {
if (tok[1] == '/') { // strcmp wouldn't work here (in case characters follow comment)
inLineComment = true;
continue;
} else if (tok[1] == '*') {
inCComment = true;
continue;
}
} else if (tok[0] == '#') { // need to ignore all preprocessor declarations
inLineComment = true; // treat them as line comments
continue; // don’t parse any further
}
}
if (!isTemplateDefn) {
if ( level ) {
if ( ! strcmp ( tok , "{" ) ) {
level ++ ;
} else if ( ! strcmp ( tok , "}" ) ) {
level -- ;
if ((!level) && inTemplateDef) { // •• ES: finish template declaration
EndTemplateDeclaration();
inTemplateDef = false;
if (defnFileName[0] != 0)
MungeFile(vRef, parID, defnFileName, true); // recursive call to this routine – neat, huh?
CloseOutfile();
}
}
} else { // no level - set context ?
if ( ! strcmp ( tok, "template" ) ) {
if (!tempFileReady) {
sprintf(other, "\r• Warning Line %d: template declaration without __TEMPLATE__ " , line ) ;
Message(C2P(other));
} else {
tempFileReady = false;
inTemplateDef = true;
if (OpenOutfile()) { // start an output file
ErrMsg("\pCreating", outFileName, err);
inTemplateDef = false;
}
}
} else if ( ! strcmp ( tok , "{" ) ) {
level ++ ;
} else if ( ! strcmp ( tok , "}" ) ) {
sprintf ( other , "\r• Error Line %d: level < 0 " , line ) ;
Message ( C2P ( other ) ) ;
}
}
}
if (inTemplateDef || isTemplateDefn) // valid token, echo tokens to macro file
if (!OutToken(tok)) {
sprintf(other, "\r• Error Line %d: invalid template declaration", line);
Message(C2P(other));
}
}
// make sure we haven't left a file hanging
if (inTemplateDef) {
CloseOutfile();
sprintf(other, "\r• Error Line %d: unfinished template declaration ", line );
Message(C2P(other));
}
if (isTemplateDefn)
EndTemplateDefn();
}
static void
MungeFile ( short vRef , long parID , unsigned char * fn, Boolean isTemplateDefn ) {
Handle text ;
short ref = 0 ;
long size ;
Boolean doWrite ;
char other [255];
if (!isTemplateDefn) {
if ((fn[fn[0]-1] != '.') || (fn[fn[0]] != 'h')) { // only read ".h" files, unless reading as template declaration
return;
}
Message ( fn ) ;
}
err = HOpenDF ( vRef , parID , fn , fsRdWrPerm , & ref ) ;
if ( err ) {
ErrMsg ( "\pOpening" , fn , err ) ;
return ;
}
err = GetEOF ( ref , & size ) ;
if ( ! err ) {
err = SetFPos ( ref , fsFromStart , 0L ) ;
}
if ( err ) {
ErrMsg ( "\pStarting" , fn , err ) ;
FSClose ( ref ) ;
return ;
}
text = NewHandle ( size ) ;
if ( ! text ) {
ErrMsg ( "\pAllocating" , fn , MemError ( ) ) ;
FSClose ( ref ) ;
return ;
}
HLock ( text ) ;
err = FSRead ( ref , & size , * text ) ;
if ( err ) {
ErrMsg ( "\pReading" , fn , err ) ;
FSClose ( ref ) ;
DisposeHandle ( text ) ;
}
HUnlock ( text ) ;
MungeHandle(text, vRef, parID, isTemplateDefn);
DisposeHandle ( text ) ;
if ( err ) {
ErrMsg ( "\pClosing" , fn , err ) ;
}
if (!isTemplateDefn)
Message ( "\p DONE\r" ) ;
}
void
MungeFolder ( long parID ) {
short ix ;
for ( ix = 1 ; ix > 0 ; ix ++ ) {
rec . hFileInfo . ioCompletion = 0L ;
rec . hFileInfo . ioFVersNum = 0 ;
rec . hFileInfo . ioNamePtr = name ;
rec . hFileInfo . ioVRefNum = vRefNum ;
rec . hFileInfo . ioDirID = parID ;
rec . hFileInfo . ioFDirIndex = ix ;
err = PBGetCatInfoAsync ( & rec ) ;
do {
Idle ( ) ;
} while ( rec . hFileInfo . ioResult == 1 ) ;
err = rec . hFileInfo . ioResult ;
if ( err ) {
break ;
}
if ( rec . hFileInfo . ioFlAttrib & 0x10 ) { /* Folder */
CopyP ( "\p\r•Entering Folder " , str ) ;
ConcP ( str , name ) ;
ConcP ( str , "\p\r" ) ;
Message ( str ) ;
MungeFolder ( rec . hFileInfo . ioDirID ) ;
Message ( "\p---- Leaving folder ----\r\r" ) ;
} else if ( rec . hFileInfo . ioFlFndrInfo . fdType == 'TEXT' ) {
MungeFile ( vRefNum , parID , name , false ) ;
}
}
}